<?php
/**
 * File: Router.php.
 * User: Yan<me@xiaoyan.me>
 * DateTime: 2017-12-19 20:49
 */

namespace App\Core;


class Router
{
    private static $routeList = [];

    private static $instance = null;

    private function __construct()
    {
    }

    /**
     * @return Router|null
     */
    public static function Instance()
    {
        if (is_null(self::$instance)) {
            self::$instance = new Router();
        }
        return self::$instance;
    }

    public static function Handle(Request $request)
    {
        $path = getRequestUri();
        if (isset(self::$routeList[$path])) {
            $ret = Middleware::Handle($request);
            if ($ret === false) return;
            $callable = self::$routeList[$path]['callable'];
            if (is_string($callable)) {
                $cls = explode('@', $callable);
                $cls_method = count($cls) >= 2 ? $cls[1] : 'index';
                $cls = new \ReflectionClass('\\' . $cls[0]);
                $instance = $cls->newInstance();
                if (method_exists($instance, $cls_method)) {
                    if (method_exists($instance, '__intEnv')) {
                        call_user_func([$instance, '__intEnv'], $request);
                    }
                    $ret = call_user_func([$instance, $cls_method], $request);
                    if($ret && is_string($ret)) {
                        echo $ret;
                    }
                    return true;
                }
            } else {
                call_user_func($callable, $request);
                return true;
            }
        }
        echo json_encode(['code' => 404, 'message' => 'resource not found']);
        return false;
    }

    /**
     * @param string $path
     * @param callable $callback
     * @param null $method
     */
    public function get($path, $callback, $method = null)
    {
        if (is_string($callback) && $method) {
            $callback = $callback . '@' . $method;
        }
        self::$routeList[strtolower($path)] = [
            'method' => 'GET',
            'callable' => $callback
        ];
    }

    /**
     * @param string $path
     * @param callable $callback
     */
    public function post($path, $callback)
    {
        self::$routeList[$path] = [
            'method' => 'POST',
            'callable' => $callback
        ];
    }
}